#ifndef _SIMPLE_PROTOCOL_H_
#define _SIMPLE_PROTOCOL_H_
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>    // standard lib functions
#include <stddef.h>    // standard definitions
#include <stdint.h>    // standard integer definition
#include <stdbool.h>   // boolean definition
#include <string.h>
#include <stdio.h>
#include "Debug.h"
#include "tag_type.h"

#include "FreeRTOS.h"
#include "Timers.h"
#include "semphr.h"

#include "buf.h"

typedef enum{
	ERR_NONE 				= 0,	//无错误
	ERR_UNKNOWN_FUNCTION 	= 1,	//未知函数
	ERR_MISSING_PARAMETER 	= 2,	//遗漏参数
	ERR_UNUSED_PARAMETERS 	= 3,	//未使用的参数
	ERR_INVALID_FUNCTION 	= 4,	//无效函数
	ERR_PARSER 				= 5,	//无法解析
	ERR_BUSY				= 0x10,	//忙
}simpleProtocol_result;

typedef enum{
	SIMPLE_PROTOCOL_COM_USB = 0,
	SIMPLE_PROTOCOL_COM_UART = 1,
	SIMPLE_PROTOCOL_COM_NUM,
}simpleProtocol_com;

typedef enum{
	SIMPLE_PROTOCOL_MODE_ASCII = 0,
	SIMPLE_PROTOCOL_MODE_HEX,
}simpleProtocol_mode;

#define PROTOCOL_USB_BIT		0x01
#define PROTOCOL_UART_BIT		0x02

#define PROTOCOL_MODE_MASK		0x01
#define PROTOCOL_MODE_ASCII		0x00
#define PROTOCOL_MODE_BINARY	0x01

#define PROTOCOL_CRC_MASK		0x02
#define PROTOCOL_CRC_ENABLE		0x02
#define PROTOCOL_CRC_DISABLE	0x00

#pragma pack (1)

typedef struct{
	uint8_t api;
	uint8_t fun;
	uint8_t params[1];
}frame_command_t;

typedef struct {
	uint8_t result;
	uint8_t resp[1];
}frame_response_t;

#pragma pack ()

typedef struct {
	uint8_t* data;
	uint16_t length;
}protocol_buf_t;


typedef struct {
	buffer_t command;
	buffer_t response;
	uint8_t flag;
}simple_protocol_context_t;


typedef enum {
	API_CLASS_SYS = 0x00,
	API_CLASS_IO = 0x01,
	API_CLASS_RF = 0x05,
	API_CLASS_MIFARE_CLASSIC = 0x0B,
	API_CLASS_MIFARE_ULTRALIGHT = 0x0C,	
	API_CLASS_15693 = 0x0D,
	API_CLASS_CRYPTO = 0x0E,
	API_CLASS_DESFIRE = 0x0F,
	API_CLASS_ISO7816 = 0x10,
	API_CLASS_ICLASS = 0x11,
	API_CLASS_ISO14443 = 0x12,
	API_CLASS_MIFARE_PLUS = 0x1B,
	API_CLASS_FELICA = 0x1D,
	API_CLASS_NTAG = 0x20,	
	API_CLASS_BLE = 0x25,
	API_CLASS_ZK = 0xFE,
	API_CLASS_UNKNOWN = 0xFF,
}api_code_t;

typedef int (*api_entry_t)(buffer_t* cmd, buffer_t* resp);

typedef struct {
	api_code_t code;
	api_entry_t entry;
}api_class_t;

typedef struct {
	uint8_t func;
	api_entry_t entry;
}api_func_t;

#define SIMPLE_API_DEFINE(_code, _entry)	\
	static const api_class_t api_ ## _code ## _entry 			\
	__attribute__((used,__section__(".api.1." # _code "_" # _entry ))) \
		= {.code = _code, .entry = _entry,}

#define SIMPLE_API_START_DEFINE	\
		static const api_class_t api_start \
		__attribute__((used,__section__(".api.0"))) \
			= {.code = API_CLASS_UNKNOWN, .entry = NULL,}
			
#define SIMPLE_API_END_DEFINE		\
		static const api_class_t api_end	\
		__attribute__((used,__section__(".api.2"))) \
			= {.code = API_CLASS_UNKNOWN, .entry = NULL,}
			
#define SIMPLE_API_START	&api_start
#define SIMPLE_API_END	&api_end

typedef int (*fun_entry_t)(const uint8_t* param, uint16_t param_len, buffer_t* response);


#define SIMPLE_PROTOCOL_HEAD_SIZE						(sizeof(uint8_t)/*api*/ + sizeof(uint8_t)/*fun*/)
#define SIMPLE_PROTOCOL_CRC_SIZE						(sizeof(uint16_t))
#define SIMPLE_PROTOCOL_FRAME_SIZE						(sp->crc_en == true) ? sp->frame_len - SIMPLE_PROTOCOL_CRC_SIZE : sp->frame_len
#define SIMPLE_PROTOCOL_PARAMS_SIZE						(SIMPLE_PROTOCOL_FRAME_SIZE - SIMPLE_PROTOCOL_HEAD_SIZE)

#define SIMPLE_PROTOCOL_VERSION							"TWN4/B1.08/NFC4.01/PRS1.04/B"
#define SIMPLE_PROTOCOL_SERNO							__DATE__ "-" __TIME__

#define API_CHECK(status)	do{	\
	if(status){							\
		LOG_E("error: %d", status); 	\
		return -1;						\
	}									\
}while(0)

typedef struct{
//		tagType		tag;
	uint8_t 	params[9];
	uint32_t	lastError;
}simpleConfig_t;

typedef enum{
	CARD_TYPE_OTHER = 0,
	CARD_TYPE_MIFARE,
	CARD_TYPE_CPU,
	CARD_TYPE_DESFIRE,
	CARD_TYPE_APLUS,
	CARD_TYPE_1569,
	CARD_TYPE_ID,
	CARD_TYPE_HIDPROX,
	CARD_TYPE_HIDICLASS,
}cardType;

typedef struct{
	cardType					type;
	uint8_t 					sak;
	uint8_t 					ats[32];
	uint8_t						ats_len;
	uint8_t 					uid[16];
	uint8_t 					uid_len;
	uint16_t					uid_bit;
	uint16_t					atqa;
	uint8_t						atqb[32];
	uint8_t 					atqb_len;
	uint8_t						atr[32];
	uint8_t						atr_len;
}simpleCardInfo_t;

typedef struct{
	uint8_t uid_len;
	uint8_t	uid[16];
}simpleBleTag_t;



extern simpleConfig_t simpleConfig;
extern simpleCardInfo_t simpleCaedInfo;
extern simpleBleTag_t simpleBleTag;

void simpleProtocol_task(void *arg);
int protocol_call_api(const api_entry_t* api_list, uint8_t api_num, 
							buffer_t* command, buffer_t* response);
int protocol_call_fun(uint8_t fun_code, const api_func_t fun_list[], uint8_t fun_num, 
		buffer_t* command, buffer_t* response);
void protocol_response_result(buffer_t* response, int result);

void simpleProtocol_Notify(uint8_t src);

#endif

